package com.haohan.cloud.scm.supply.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.haohan.cloud.scm.api.bill.dto.BillInfoDTO;
import com.haohan.cloud.scm.api.bill.feign.PayableBillFeignService;
import com.haohan.cloud.scm.api.bill.feign.SettlementFeignService;
import com.haohan.cloud.scm.api.bill.req.BillInfoFeignReq;
import com.haohan.cloud.scm.api.constant.ScmCacheNameConstant;
import com.haohan.cloud.scm.api.constant.enums.bill.OrderTypeEnum;
import com.haohan.cloud.scm.api.constant.enums.common.UseStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.crm.PayStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.saleb.BillTypeEnum;
import com.haohan.cloud.scm.api.constant.enums.saleb.BuyOrderStatusEnum;
import com.haohan.cloud.scm.api.goods.dto.GoodsExtDTO;
import com.haohan.cloud.scm.api.goods.dto.GoodsModelDTO;
import com.haohan.cloud.scm.api.goods.entity.GoodsModel;
import com.haohan.cloud.scm.api.goods.feign.GoodsFeignService;
import com.haohan.cloud.scm.api.goods.feign.GoodsModelFeignService;
import com.haohan.cloud.scm.api.goods.req.GoodsFeignReq;
import com.haohan.cloud.scm.api.goods.req.GoodsModelFeignReq;
import com.haohan.cloud.scm.api.goods.req.GoodsModelReq;
import com.haohan.cloud.scm.api.goods.vo.GoodsVO;
import com.haohan.cloud.scm.api.manage.entity.Merchant;
import com.haohan.cloud.scm.api.manage.entity.Shop;
import com.haohan.cloud.scm.api.manage.entity.UPassport;
import com.haohan.cloud.scm.api.manage.feign.MerchantFeignService;
import com.haohan.cloud.scm.api.manage.feign.ShopFeignService;
import com.haohan.cloud.scm.api.manage.feign.UPassportFeignService;
import com.haohan.cloud.scm.api.manage.req.MerchantFeignReq;
import com.haohan.cloud.scm.api.manage.vo.MerchantShopVO;
import com.haohan.cloud.scm.api.manage.vo.MerchantVO;
import com.haohan.cloud.scm.api.opc.entity.ShipRecord;
import com.haohan.cloud.scm.api.opc.feign.ShipRecordFeignService;
import com.haohan.cloud.scm.api.opc.req.ShipRecordReq;
import com.haohan.cloud.scm.api.opc.req.ship.ShipRecordFeignReq;
import com.haohan.cloud.scm.api.purchase.entity.SupplierRelation;
import com.haohan.cloud.scm.api.purchase.feign.SupplierRelationFeignService;
import com.haohan.cloud.scm.api.purchase.req.SupplierRelationReq;
import com.haohan.cloud.scm.api.saleb.entity.BuyOrderDetail;
import com.haohan.cloud.scm.api.saleb.feign.BuyOrderDetailFeignService;
import com.haohan.cloud.scm.api.saleb.feign.BuyOrderFeignService;
import com.haohan.cloud.scm.api.saleb.req.BuyOrderDetailReq;
import com.haohan.cloud.scm.api.saleb.req.BuyOrderFeignReq;
import com.haohan.cloud.scm.api.saleb.vo.BuyOrderVO;
import com.haohan.cloud.scm.api.supply.entity.Supplier;
import com.haohan.cloud.scm.api.supply.entity.SupplierGoods;
import com.haohan.cloud.scm.api.sys.admin.feign.SysDeptFeignService;
import com.haohan.cloud.scm.api.sys.admin.feign.SystemUserFeignService;
import com.haohan.cloud.scm.common.tools.exception.EmptyDataException;
import com.haohan.cloud.scm.common.tools.exception.ErrorDataException;
import com.haohan.cloud.scm.common.tools.util.RUtil;
import com.haohan.cloud.scm.supply.service.SupplierService;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;

/**
 * @author xwx
 * @date 2019/6/12
 */
@Log4j2
@Component
@AllArgsConstructor
public class ScmSupplyUtils {
    private final SupplierService supplierService;
    private final GoodsFeignService goodsFeignService;
    private final GoodsModelFeignService goodsModelFeignService;
    private final SupplierRelationFeignService supplierRelationFeignService;
    private final UPassportFeignService uPassportFeignService;
    private final ShopFeignService shopFeignService;
    private final MerchantFeignService merchantFeignService;
    private final BuyOrderFeignService buyOrderFeignService;
    private final BuyOrderDetailFeignService buyOrderDetailFeignService;
    private final ShipRecordFeignService shipRecordFeignService;
    private final PayableBillFeignService payableBillFeignService;
    private final SysDeptFeignService sysDeptFeignService;
    private final SystemUserFeignService systemUserFeignService;
    private final SettlementFeignService settlementFeignService;

    /**
     * 根据id 查询 uPassport
     *
     * @param id
     * @return
     */
    public UPassport queryUPassportById(String id) {
        R<UPassport> byId = uPassportFeignService.getById(id, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(byId) || byId.getData() == null) {
            throw new EmptyDataException();
        }
        UPassport data = byId.getData();
        return data;
    }


    /**
     * 查询查询供应商信息
     * todo 需移动
     *
     * @param pmId
     * @param uid
     * @return
     */
    public Supplier fetchByUid(String pmId, String uid) {
        // 供应商
        QueryWrapper<Supplier> querySupplier = new QueryWrapper<>();
        querySupplier.lambda()
                .eq(Supplier::getPmId, pmId)
                .eq(Supplier::getPassportId, uid);
        Supplier supplier = supplierService.getOne(querySupplier);
        if (null == supplier) {
            throw new ErrorDataException("供应商信息有误");
        }
        return supplier;
    }

    /**
     * 采购员工管理供应商信息(判断供应商是否被该采购员工管理)
     *
     * @param uid
     * @return
     */
    public SupplierRelation fetchByBuyerUid(String uid, String supplierId) {
        // 采购员
        SupplierRelationReq supplierRelationReq = new SupplierRelationReq();
        supplierRelationReq.setEmployeeId(uid);
        supplierRelationReq.setSupplierId(supplierId);
        supplierRelationReq.setUseStatus(UseStatusEnum.enabled);
        R r = supplierRelationFeignService.getOneBySupplierRelationReq(supplierRelationReq, SecurityConstants.FROM_IN);
        if (RUtil.isSuccess(r) || r.getData() == null) {
            throw new ErrorDataException("没有这个采购员");
        }
        SupplierRelation supplierRelation = BeanUtil.toBean(r.getData(), SupplierRelation.class);
        return supplierRelation;
    }

    /**
     * 商品规格信息
     *
     * @param goodsModelReq
     * @return
     */
    public GoodsModel fetchGoodsModel(GoodsModelReq goodsModelReq) {
        R r = goodsModelFeignService.getOneByGoodsModelReq(goodsModelReq, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r) || r.getData() == null) {
            throw new ErrorDataException("关联零售商品规格出错");
        }
        return BeanUtil.toBean(r.getData(), GoodsModel.class);
    }

    /**
     * 商品规格信息 (关联了商品信息)
     *
     * @param goodsModelId
     * @return
     */
    public GoodsModelDTO fetchGoodsModelDTO(String goodsModelId) {
        R<GoodsModelDTO> r = goodsModelFeignService.getInfoById(goodsModelId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("商品规格信息查询失败");
        }
        return r.getData();
    }

    /**
     * 根据 moderId 带 merchantId/shopId
     *
     * @param query
     * @return 可null
     */
    public GoodsModelDTO fetchGoodsModelDTO(GoodsModelFeignReq query) {
        R<GoodsModelDTO> r = goodsModelFeignService.fetchInfo(query, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("商品规格信息查询失败");
        }
        return r.getData();
    }

    /**
     * 根据 modelIdSet 查询规格列表
     *
     * @param req
     * @return
     */
    public List<GoodsModelDTO> findGoodsModelList(GoodsModelFeignReq req) {
        R<List<GoodsModelDTO>> r = goodsModelFeignService.findGoodsModelList(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("商品规格信息列表查询失败");
        }
        return r.getData();
    }

    /**
     * 分页查询商品列表
     *
     * @param req
     * @return
     */
    public Page<GoodsExtDTO> fetchGoodsPage(GoodsFeignReq req) {
        R<Page<GoodsExtDTO>> r = goodsFeignService.findExtPage(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("商品列表查询失败");
        }
        return r.getData();
    }

    @Cacheable(value = ScmCacheNameConstant.MANAGE_PLATFORM_MERCHANT, key = "0")
    public Merchant fetchPlatformMerchant() {
        R<Merchant> r = merchantFeignService.fetchPlatformMerchant(SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询租户的平台商家失败");
        } else if (null == r.getData()) {
            throw new ErrorDataException("查询平台商家失败");
        }
        return r.getData();
    }

    /**
     * 获取商家店铺
     *
     * @param merchantId
     * @return
     */
    public MerchantShopVO fetchMerchantShop(String merchantId) {
        R<MerchantShopVO> r = shopFeignService.fetchMerchantShop(merchantId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("获取商家店铺失败");
        }
        return r.getData();
    }

    public Shop fetchShopById(String shopId) {
        R<Shop> r = shopFeignService.getById(shopId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("获取店铺失败");
        }
        if (null == r.getData()) {
            throw new ErrorDataException("店铺有误");
        }
        return r.getData();
    }

    /**
     * 获取商品详情
     *
     * @param req 必须goodsId, 可选 buyerId、pricingDate
     * @return
     */
    @Cacheable(value = ScmCacheNameConstant.GOODS_INFO_DETAIL, key = "#req.goodsId+':'+#req.pricingMerchantId+#req.pricingDate+#req.buyerId")
    public GoodsVO fetchGoodsInfoById(GoodsFeignReq req) {
        R<GoodsVO> r = goodsFeignService.fetchGoodsInfoById(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("获取商品详情时失败" + r.getMsg());
        }
        return r.getData();
    }

    /**
     * 根据merchantId 集合和 启用状态 查询列表
     *
     * @param req
     * @return
     */
    public List<MerchantVO> findMerchantList(MerchantFeignReq req) {
        R<List<MerchantVO>> r = merchantFeignService.findMerchantList(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("获取商家列表失败");
        }
        return r.getData();
    }

    /**
     * 根据供应商品创建平台商品
     *
     * @param shopId        创建商品的平台店铺， 为空时默认平台店铺
     * @param supplyGoodsId
     * @return
     */
    public List<SupplierGoods> createGoodsBySupplyGoods(String shopId, String supplyGoodsId) {
        GoodsFeignReq req = new GoodsFeignReq();
        req.setShopId(shopId);
        req.setGoodsId(supplyGoodsId);
        R<List<SupplierGoods>> r = goodsFeignService.createGoodsBySupplyGoods(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("根据供应商品创建平台商品失败:" + r.getMsg());
        }
        return r.getData();
    }

    /**
     * 采购单信息查询
     *
     * @param buyOrderSn
     * @return
     */
    public BuyOrderVO fetchBuyOrderInfo(String buyOrderSn) {
        R<BuyOrderVO> r = buyOrderFeignService.fetchInfo(buyOrderSn, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r) || null == r.getData()) {
            throw new ErrorDataException("查询采购单详情时失败");
        }
        return r.getData();
    }

    public BuyOrderDetail fetchBuyOrderDetail(String buyDetailSn) {
        BuyOrderDetailReq req = new BuyOrderDetailReq();
        req.setBuyDetailSn(buyDetailSn);
        R<BuyOrderDetail> r = buyOrderDetailFeignService.getOneByBuyOrderDetailReq(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r) || null == r.getData()) {
            throw new ErrorDataException("查询采购单明细时失败");
        }
        return r.getData();
    }

    /**
     * 供应订单创建发货记录
     *
     * @param supplySn
     */
    public void createShipRecord(String supplySn) {
        ShipRecordFeignReq req = new ShipRecordFeignReq();
        req.setOrderSn(supplySn);
        req.setOrderType(OrderTypeEnum.supply);
        R<ShipRecord> r = shipRecordFeignService.createShipRecordByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("供应订单创建发货记录时失败" + r.getMsg());
        }
    }


    public boolean deleteShipRecord(String supplySn, OrderTypeEnum type) {
        ShipRecordFeignReq req = new ShipRecordFeignReq();
        req.setOrderSn(supplySn);
        req.setOrderType(type);
        R<Boolean> r = shipRecordFeignService.deleteShipRecordByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("删除发货记录时失败");
        }
        return r.getData();
    }


    public ShipRecord fetchShipRecord(String supplySn) {
        ShipRecordReq req = new ShipRecordReq();
        req.setOrderSn(supplySn);
        R<ShipRecord> r = shipRecordFeignService.getOneByShipRecordReq(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询发货记录时失败");
        }
        return r.getData();
    }

    /**
     * 创建供应账单:采购应付
     *
     * @param supplySn
     * @param advanceAmount
     * @return
     */
    public BillInfoDTO createPayableBill(String supplySn, BigDecimal advanceAmount) {
        BillInfoDTO query = new BillInfoDTO();
        query.setOrderSn(supplySn);
        query.setBillType(BillTypeEnum.purchase);
        query.setAdvanceAmount(advanceAmount);
        R<BillInfoDTO> r = payableBillFeignService.createBill(query, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException(r.getMsg());
        }
        return r.getData();
    }

    public boolean deleteBillByOrder(String supplySn, BillTypeEnum type) {
        BillInfoFeignReq req = new BillInfoFeignReq();
        req.setOrderSn(supplySn);
        req.setBillType(type);
        R<Boolean> r = payableBillFeignService.deleteBillByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("删除账单失败");
        }
        return r.getData();
    }

    /**
     * 根据部门id查询
     *
     * @param deptId
     * @return
     */
    public SysDept fetchDeptById(String deptId) {
        if (StrUtil.isEmpty(deptId)) {
            return null;
        }
        R<SysDept> r = sysDeptFeignService.getById(deptId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询部门失败");
        }
        return r.getData();
    }

    /**
     * 查询 用户
     *
     * @return 可为null
     */
    public UserInfo fetchUserById(String id) {
        if (StrUtil.isEmpty(id)) {
            return null;
        }
        R<UserInfo> resp = systemUserFeignService.infoById(id, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(resp) || null == resp.getData()) {
            throw new ErrorDataException("用户查询失败");
        }
        return resp.getData();
    }

    public UserDTO addUser(UserDTO user) {
        R<UserDTO> r = systemUserFeignService.addUser(user, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("新增用户失败");
        }
        // 绑定通行证
        UPassport uPassport = new UPassport();
        uPassport.setTelephone(user.getPhone());
        uPassport.setLoginName(user.getUsername());
        uPassport.setPassword(user.getPassword());
        uPassport.setAvatar(user.getAvatar());
        String uid = addUPassPort(uPassport).getId();
        // uid 存入
        r.getData().setOscId(uid);
        return r.getData();
    }

    /**
     * 更新用户信息
     * 修改所有信息，修改用户角色
     *
     * @param user id
     * @return
     */
    public Boolean updateUser(UserDTO user) {
        R<Boolean> r = systemUserFeignService.updateUser(user, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("修改用户失败");
        }
        return r.getData();
    }

    /**
     * 新增通行证账号, 相同手机号会覆盖以前的
     *
     * @param uPassport
     * @return
     */
    public UPassport addUPassPort(UPassport uPassport) {
        R<UPassport> r = uPassportFeignService.add(uPassport, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("新增通行证账号时失败");
        }
        return r.getData();
    }

    public Merchant fetchMerchantById(String merchantId) {
        R<Merchant> r = merchantFeignService.getById(merchantId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询商家时失败");
        }
        return r.getData();
    }

    public PayStatusEnum queryOrderPayStatus(String orderSn) {
        R<PayStatusEnum> r = settlementFeignService.queryOrderPayStatus(orderSn, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询订单支付状态时失败");
        }
        return r.getData();
    }

    public void deleteUser(String userId) {
        Integer id;
        try {
            id = NumberUtil.parseInt(userId);
            if (id == 0) {
                id = null;
            }
        } catch (Exception e) {
            id = null;
        }
        if (null != id) {
            UserDTO user = new UserDTO();
            user.setUserId(id);
            R<Boolean> r = systemUserFeignService.deleteUser(user, SecurityConstants.FROM_IN);
            if (RUtil.isFailed(r)) {
                throw new ErrorDataException("删除用户时失败" + r.getMsg());
            }
        }
    }

    /**
     * 商品规格库存扣减
     *
     * @param storageList
     */
    public void modelStorageSubtract(List<GoodsModel> storageList) {
        try {
            GoodsModelFeignReq req = new GoodsModelFeignReq();
            req.setModelList(storageList);
            R<Boolean> r = goodsModelFeignService.modelStorageSubtract(req, SecurityConstants.FROM_IN);
            if (RUtil.isFailed(r)) {
                log.debug("==商品规格库存扣减时失败={}===", r.getMsg());
            }
        } catch (Exception e) {
            log.debug("==商品规格库存扣减时有误");
            e.printStackTrace();
        }
    }

    /**
     * 采购订单状态改变(不包括已取消)
     * 采购单状态：1.已下单2.待确认3.成交4.取消  5.待发货 6.待收货
     *
     * @param buyOrderSn
     * @param status     (修改后状态)
     * @return
     */
    public boolean updateBuyOrderStatus(String buyOrderSn, BuyOrderStatusEnum status) {
        BuyOrderFeignReq req = new BuyOrderFeignReq();
        req.setBuyOrderSn(buyOrderSn);
        req.setStatus(status);
        R<Boolean> r = buyOrderFeignService.updateOrderStatus(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("修改采购单时失败:" + r.getMsg());
        }
        return r.getData();
    }


//    /**
//     * 查询采购单
//     * @param req
//     * @return
//     */
//    public PurchaseOrder fetchPurchaseOrder(PurchaseOrderReq req){
//        R r = purchaseOrderFeignService.getOneByPurchaseOrderReq(req, SecurityConstants.FROM_IN);
//        if (!RUtil.isSuccess(r) || null==r.getData()) {
//            throw new ErrorDataException("采购单为空");
//        }
//        return BeanUtil.toBean(r.getData(), PurchaseOrder.class);
//    }
//
//    /**
//     * 查询采购单明细列表
//     * @param req
//     * @return
//     */
//    public List<PurchaseOrderDetail> fetchPurchaseOrderDetail(PurchaseOrderDetailReq req){
//        R r = purchaseOrderDetailFeignService.getPurchaseOrderDetailList(req, SecurityConstants.FROM_IN);
//        if (!RUtil.isSuccess(r)) {
//            throw new ErrorDataException("采购单明细列表为空");
//        }
//        return BeanUtil.toBean(r.getData(), List.class);
//    }
//
//    /**
//     * 查询退货单
//     *
//     * @param req pmId
//     * @return
//     */
//    public ReturnOrder queryReturnOrder(ReturnOrderReq req) {
//        R r = returnOrderFeignService.getOneByReturnOrderReq(req, SecurityConstants.FROM_IN);
//        if (!RUtil.isSuccess(r)) {
//            throw new ErrorDataException("查询退货单有误");
//        } else if (null == r.getData()) {
//            return null;
//        }
//        return BeanUtil.toBean(r.getData(), ReturnOrder.class);
//    }
//
//
//    /**
//     * 查询采购商
//     * @param buyerReq
//     * @return
//     */
//    public Buyer queryBuyer(BuyerReq buyerReq) {
//        R r = buyerFeignService.getOneByBuyerReq(buyerReq, SecurityConstants.FROM_IN);
//        if (!RUtil.isSuccess(r)) {
//            throw new ErrorDataException("查询采购商有误");
//        } else if (null == r.getData()) {
//            return null;
//        }
//        return BeanUtil.toBean(r.getData(), Buyer.class);
//    }
//
//    /**
//     * 查询 可退款的退货单  根据pmId/ returnSn
//     *
//     * @param req
//     * @return
//     */
//    public ReturnOrder fetchRefund(ReturnOrderReq req) {
//        R r = returnOrderFeignService.fetchRefund(req, SecurityConstants.FROM_IN);
//        if (!RUtil.isSuccess(r)) {
//            throw new ErrorDataException("查询可退款的退货单有误");
//        } else if (null == r.getData()) {
//            return null;
//        }
//        return BeanUtil.toBean(r.getData(), ReturnOrder.class);
//    }


}
